package customer

import (
	"fmt"
	"github.com/go-sql-driver/mysql"
	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
	"server/global"
	CustomerModel "server/model/customer"
	customerReq "server/model/customer/request"
	customerRes "server/model/customer/response"
	"server/utils"
	"strings"
)

// AddOrUpdateBug 添加/更新漏洞
func (cs *CustomerService) AddOrUpdateBug(bug customerReq.CustomerBug) (*customerRes.CustomerBugResult, string, error) {
	var customerBugModel CustomerModel.CustomerBugModel
	var customerBugResult customerRes.CustomerBugResult
	var action string

	if bug.ID == 0 {
		action = "添加"
		// 创建新的 customerBugModel 对象
		customerBugModel = CustomerModel.CustomerBugModel{
			CustomerID:      bug.CustomerId,
			EnvVersion:      bug.EnvVersion,
			CVE:             bug.CVE,
			AttachmentID:    bug.AttachmentID,
			BugLevel:        bug.BugLevel,
			Status:          bug.Status,
			APP:             bug.APP,
			DiscoverVersion: bug.DiscoverVersion,
			FeedbackID:      bug.Feedback,
			FixVersion:      bug.FixVersion,
			FixerID:         bug.Fixer,
			BugDesc:         bug.BugDesc,
			VerifyInfo:      bug.VerifyInfo,
			FixSuggest:      bug.FixSuggest,
			Comment:         bug.Comment,
			Tags:            bug.Tags,
		}

		// 执行添加操作
		if err := global.TD27_DB.Create(&customerBugModel).Error; err != nil {
			return nil, action, err
		}
	} else {
		action = "修改"
		//// 根据 bug.ID 查询对应的 customerBugModel 对象
		if err := global.TD27_DB.First(&customerBugModel, bug.ID).Error; err != nil {
			global.TD27_LOG.Error("编辑客户漏洞 -> 查询Id", zap.Error(err))
			return nil, action, err
		}
		//
		//// 更新 customerBugModel 对象的属性值
		customerBugModel.CustomerID = bug.CustomerId
		customerBugModel.EnvVersion = bug.EnvVersion
		customerBugModel.CVE = bug.CVE
		customerBugModel.AttachmentID = bug.AttachmentID
		customerBugModel.BugLevel = bug.BugLevel
		customerBugModel.Status = bug.Status
		customerBugModel.APP = bug.APP
		customerBugModel.DiscoverVersion = bug.DiscoverVersion
		customerBugModel.FeedbackID = bug.Feedback
		customerBugModel.FixVersion = bug.FixVersion
		customerBugModel.FixerID = bug.Fixer
		customerBugModel.BugDesc = bug.BugDesc
		customerBugModel.VerifyInfo = bug.VerifyInfo
		customerBugModel.FixSuggest = bug.FixSuggest
		customerBugModel.Comment = bug.Comment
		customerBugModel.Tags = bug.Tags

		// 执行修改操作
		if err := global.TD27_DB.Save(&customerBugModel).Error; err != nil {
			global.TD27_LOG.Error("编辑客户漏洞 -> update", zap.Error(err))
			return nil, action, err
		}
	}

	// 构造返回结果
	customerBugResult.ID = customerBugModel.ID
	customerBugResult.UpdatedAt = customerBugModel.UpdatedAt
	customerBugResult.CustomerId = customerBugModel.CustomerID
	customerBugResult.EnvVersion = customerBugModel.EnvVersion
	customerBugResult.CVE = customerBugModel.CVE
	customerBugResult.AttachmentID = customerBugModel.AttachmentID
	customerBugResult.BugLevel = customerBugModel.BugLevel
	customerBugResult.Status = customerBugModel.Status
	customerBugResult.APP = customerBugModel.APP
	customerBugResult.DiscoverVersion = customerBugModel.DiscoverVersion
	customerBugResult.Feedback = customerBugModel.FeedbackID
	customerBugResult.FixVersion = customerBugModel.FixVersion
	customerBugResult.Fixer = customerBugModel.FixerID
	customerBugResult.BugDesc = customerBugModel.BugDesc
	customerBugResult.VerifyInfo = customerBugModel.VerifyInfo
	customerBugResult.FixSuggest = customerBugModel.FixSuggest
	customerBugResult.Comment = customerBugModel.Comment
	customerBugResult.Tags = customerBugModel.Tags

	return &customerBugResult, action, nil
}

// GetBug 获取漏洞列表
func (cs *CustomerService) GetBug(BugSp customerReq.BugSearchParams) ([]customerRes.CustomerBugResult, int64, error) {
	var bugResult []customerRes.CustomerBugResult
	var total int64

	db := global.TD27_DB.Model(&CustomerModel.CustomerBugModel{}).
		Select("customer_bug.*, customer.name, feedback_people.id as feedback, feedback_people.name AS feedback_name, fixer_people.id AS fixer, fixer_people.name AS fixer_name").
		Joins("JOIN customer ON customer_bug.customer_id = customer.id").
		Joins("LEFT JOIN people AS feedback_people ON customer_bug.feedback_id = feedback_people.id").
		Joins("LEFT JOIN people AS fixer_people ON customer_bug.fixer_id = fixer_people.id").
		Order("customer_bug.updated_at DESC").
		Find(&bugResult)

	if BugSp.Name != "" {
		db = db.Where("customer.name LIKE ?", "%"+BugSp.Name+"%")
	}
	if BugSp.CVE != "" {
		db = db.Where("customer_bug.cve LIKE ?", "%"+BugSp.CVE+"%")
	}
	if BugSp.Tag != "" {
		db = db.Where("customer_bug.tags LIKE ?", "%"+BugSp.Tag+"%")
	}
	if BugSp.APP != 0 {
		db = db.Where("customer_bug.app = ?", BugSp.APP)
	}
	if BugSp.Status != 0 {
		db = db.Where("customer_bug.status = ?", BugSp.Status)
	}
	if BugSp.BugLevel != 0 {
		db = db.Where("customer_bug.bug_level = ?", BugSp.BugLevel)
	}

	err := db.Count(&total).Error
	if BugSp.PageSize != 0 && BugSp.Page != 0 {
		db.Limit(BugSp.PageSize).Offset(BugSp.PageSize * (BugSp.Page - 1))
	}
	db.Find(&bugResult)
	if err != nil {
		return bugResult, total, fmt.Errorf("查询 CustomerBugModel 失败: %v", err)
	}
	// 返回结果
	return bugResult, total, nil
}

// SwitchBugStatus 切换bug状态
func (cs *CustomerService) SwitchBugStatus(bugStatus customerReq.SwitchBugStatus) (*customerRes.CustomerBugResult, error) {
	var customerBugModel CustomerModel.CustomerBugModel
	var customerBugResult customerRes.CustomerBugResult

	// id不为空并且ids为空，则走单个切换bug状态的逻辑
	if bugStatus.ID != 0 && bugStatus.IDS == "" {
		m := fmt.Sprintf("bugStatus.ID: %d,bugStatus.IDS: %s", bugStatus.ID, bugStatus.IDS)
		global.TD27_LOG.Error("没走批量操作")
		global.TD27_LOG.Error(m)
		//// 根据 bug.ID 查询对应的 customerBugModel 对象
		if err := global.TD27_DB.First(&customerBugModel, bugStatus.ID).Error; err != nil {
			global.TD27_LOG.Error("切换漏洞状态 -> 查询Id", zap.Error(err))
			return nil, err
		}
		// 更新 customerBugModel 对象的属性值
		customerBugModel.Status = bugStatus.Status
		customerBugModel.FixVersion = bugStatus.FixVersion
		customerBugModel.FixerID = bugStatus.Fixer

		// 执行修改操作
		if err := global.TD27_DB.Save(&customerBugModel).Error; err != nil {
			global.TD27_LOG.Error("编辑客户漏洞 -> update", zap.Error(err))
			return nil, err
		}

		// 构造返回结果
		customerBugResult.ID = customerBugModel.ID
		customerBugResult.UpdatedAt = customerBugModel.UpdatedAt
		customerBugResult.CustomerId = customerBugModel.CustomerID
		customerBugResult.EnvVersion = customerBugModel.EnvVersion
		customerBugResult.CVE = customerBugModel.CVE
		customerBugResult.BugLevel = customerBugModel.BugLevel
		customerBugResult.Status = customerBugModel.Status
		customerBugResult.APP = customerBugModel.APP
		customerBugResult.DiscoverVersion = customerBugModel.DiscoverVersion
		customerBugResult.Feedback = customerBugModel.FeedbackID
		customerBugResult.FixVersion = customerBugModel.FixVersion
		customerBugResult.Fixer = customerBugModel.FixerID
		customerBugResult.BugDesc = customerBugModel.BugDesc
		customerBugResult.VerifyInfo = customerBugModel.VerifyInfo
		customerBugResult.FixSuggest = customerBugModel.FixSuggest
		customerBugResult.Comment = customerBugModel.Comment
		customerBugResult.Tags = customerBugModel.Tags
		return &customerBugResult, nil
	} else if bugStatus.ID == 0 && bugStatus.IDS != "" {
		global.TD27_LOG.Error("走批量操作了")
		// ids不为空且id为空，则走批量操作
		// 开启事务
		tx := global.TD27_DB.Begin()
		// 确保在出现错误或panic的情况下回滚事务
		defer func() {
			if r := recover(); r != nil {
				tx.Rollback()
			}
		}()

		// 切割id
		ids := strings.Split(bugStatus.IDS, ",")
		// 循环处理每个id
		for _, id := range ids {
			var customerBugModel CustomerModel.CustomerBugModel
			// 根据 id 查询对应的 customerBugModel 对象
			if err := tx.First(&customerBugModel, id).Error; err != nil {
				global.TD27_LOG.Error("批量切换漏洞状态 -> 查询Id", zap.Error(err))
				tx.Rollback()
				return nil, err
			}
			// 更新 customerBugModel 对象的属性值
			customerBugModel.Status = bugStatus.Status
			customerBugModel.FixVersion = bugStatus.FixVersion
			customerBugModel.FixerID = bugStatus.Fixer

			// 执行修改操作
			if err := tx.Save(&customerBugModel).Error; err != nil {
				global.TD27_LOG.Error("编辑客户漏洞 -> update", zap.Error(err))
				tx.Rollback()
				return nil, err
			}
		}
		tx.Commit()
		return nil, nil
	} else {
		msg := "没有接收到id或ids(或者同时传递了id及ids)，不执行任何操作!"
		global.TD27_LOG.Warn(msg)
		return nil, fmt.Errorf(msg)
	}
}

// DeleteBug 删除漏洞
func (cs *CustomerService) DeleteBug(id int) (err error) {
	return global.TD27_DB.Where("id = ?", id).Unscoped().Delete(&CustomerModel.CustomerBugModel{}).Error
}

// BatchDeleteBug 批量删除漏洞
func (cs *CustomerService) BatchDeleteBug(batchData customerReq.BatchDeleteBug) (err error) {
	ids := strings.Split(batchData.IDS, ",")
	// 开启事务
	tx := global.TD27_DB.Begin()
	// 确保在出现错误或painc的情况下回滚事务
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	for _, id := range ids {
		err = tx.Where("id = ?", id).Unscoped().Delete(&CustomerModel.CustomerBugModel{}).Error
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	tx.Commit()
	return nil
}

// BatchAddBug 批量添加漏洞
func (cs *CustomerService) BatchAddBug(Bugs customerReq.BatchAddBug, filePath string) (importList customerRes.ImportList, err error) {
	// 初始化 importList
	importList = customerRes.ImportList{
		Success: customerRes.ImportResult{
			CVEList:   []string{},
			ErrorInfo: make(customerRes.ErrorInfo), // 初始化 ErrorInfo 映射
		},
		Fail: customerRes.ImportResult{
			CVEList:   []string{},
			ErrorInfo: make(customerRes.ErrorInfo), // 初始化 ErrorInfo 映射
		},
	}

	// 读取上传的文件
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return
	}
	defer func() {
		if err := f.Close(); err != nil {
			global.TD27_LOG.Error(fmt.Sprintf("关闭文件句柄失败，error：%s", err))
		}
	}()

	// 获取 Sheet2
	rows, err := f.GetRows("Sheet2")
	if err != nil {
		return
	}

	// 开启事务
	tx := global.TD27_DB.Begin()

	// 确保在出现错误或painc的情况下回滚事务
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 校验是否有空值（excel中的列值都不可为空）
	for rowNum, row := range rows {
		if rowNum == 0 {
			continue
		}
		for colNum, col := range row {
			if colNum == 1 || colNum == 2 {
				err = checkEmptyNum(col, colNum, rowNum)
			} else {
				err = checkEmptyString(col, colNum, rowNum)
			}
			if err != nil {
				return
			}
		}
	}

	var bugLevel uint8
	var app uint8
	var cve string
	// 循环写入数据库
	for rowNum, row := range rows {
		if rowNum == 0 {
			continue
		}
		bugLevel, _ = utils.StringToUint8(row[1])
		app, _ = utils.StringToUint8(row[2])
		cve = utils.GetCveID(row[0])

		// 创建新的 customerBugModel 对象
		customerBugModel := CustomerModel.CustomerBugModel{
			CustomerID:      Bugs.CustomerId,
			EnvVersion:      Bugs.EnvVersion,
			CVE:             cve,
			AttachmentID:    Bugs.AttachmentID,
			BugLevel:        bugLevel,
			APP:             app,
			DiscoverVersion: row[3],
			FeedbackID:      Bugs.Feedback,
			BugDesc:         row[4],
			VerifyInfo:      row[5],
			FixSuggest:      row[6],
			Comment:         Bugs.Comment,
			Tags:            Bugs.Tags,
		}

		// 执行添加操作

		err := tx.Create(&customerBugModel).Error

		if err != nil {
			importList.Fail.Total += 1
			importList.Fail.CVEList = append(importList.Fail.CVEList, cve)
			mysqlErr, _ := err.(*mysql.MySQLError)
			global.TD27_LOG.Error(mysqlErr.Message)
			importList.Fail.ErrorInfo[cve] = mysqlErr.Message
		} else {
			importList.Success.Total += 1
			importList.Success.CVEList = append(importList.Success.CVEList, cve)
		}

	}

	tx.Commit()
	return
}

func checkEmptyString(col string, index int, rowNum int) error {
	global.TD27_LOG.Warn(col)
	if strings.Trim(col, " \t\n\r") == "" {
		return fmt.Errorf("第%d行，第%d列的数据为空，请补充后重新提交", rowNum+1, index+1)
	}
	return nil
}
func checkEmptyNum(col string, index int, rowNum int) error {
	value, _ := utils.StringToUint8(col)
	if value == 0 {
		return fmt.Errorf("第%d行，第%d列的数据为空或0，请补充后重新提交", rowNum+1, index+1)
	}
	return nil
}
